﻿using System;
using System.Globalization;
using System.IO;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;

namespace Spiders
{
    class BaiduRobotHelper
    {
        // 基础 URL
        private static readonly string BaseUrl = "http://zhidao.baidu.com";
        // 认证 URL
        private static readonly string PassportUrl = "https://passport.baidu.com";

        /// <summary>
        /// 获取百度知道主页的Http响应
        /// </summary>
        /// <returns></returns>
        public static HttpWebResponse GetZhidaoMainPageResponse()
        {
            HttpWebRequest request = HttpWebRequestUtility.CreateGetHttpRequest(BaseUrl + "/");
            request.Accept = "text/html, application/xhtml+xml, */*";
            request.Headers.Add("Accept-Language", "en-US,en;q=0.8,zh-Hans-CN;q=0.5,zh-Hans;q=0.3");
            request.Headers.Add("Accept-Encoding", "gzip, deflate");
            request.Headers.Add("DNT", "1");
            request.Host = "zhidao.baidu.com";
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            return response;
        }

        /// <summary>
        /// 处理服务器发回的BAIDUID Cookie
        /// </summary>
        /// <param name="cookies"></param>
        /// <returns></returns>
        public static Cookie ZhidaoMainPageCookieHandler(string cookies)
        {
            string lastCookie = cookies.Substring(cookies.LastIndexOf("BAIDUID="));
            Cookie BAIDUID = new Cookie();
            string[] lastCookieArray = lastCookie.Split(';');
            foreach (string lastCookiePair in lastCookieArray)
            {
                string[] lastCookiePairArray = lastCookiePair.Split('=');
                if (lastCookiePairArray[0].ToUpper().Trim() == "BAIDUID")
                {
                    BAIDUID.Name = lastCookiePairArray[0];
                    BAIDUID.Value = lastCookiePairArray[1] + "=" + lastCookiePairArray[2];
                }
                if (lastCookiePairArray[0].ToLower().Trim() == "expires")
                {
                    CultureInfo provider = CultureInfo.InvariantCulture;
                    BAIDUID.Expires = DateTime.ParseExact(lastCookiePairArray[1], "ddd, dd'-'MMM'-'yy HH':'mm':'ss 'GMT'", provider, DateTimeStyles.AdjustToUniversal).ToLocalTime();
                }
                if (lastCookiePairArray[0].ToLower().Trim() == "path")
                {
                    BAIDUID.Path = lastCookiePairArray[1];
                }
                if (lastCookiePairArray[0].ToLower().Trim() == "domain")
                {
                    BAIDUID.Domain = lastCookiePairArray[1];
                }
                // Cookie的版本必须为0，否则传不过去
                //if (lastCookiePairArray[0].ToLower().Trim() == "version")
                //{
                //    BAIDUID.Version = Convert.ToInt32(lastCookiePairArray[1]);
                //}
            }
            BAIDUID.Secure = false;
            BAIDUID.HttpOnly = false;
            return BAIDUID;
        }

        /// <summary>
        /// 获取新的BAIDUID Cookie
        /// </summary>
        /// <param name="collection"></param>
        /// <returns></returns>
        public static HttpWebResponse GetNewBaiduIDCookie(CookieCollection collection)
        {
            string url = BaseUrl + "/s/toutu/promotion.js";
            HttpWebRequest request = HttpWebRequestUtility.CreateGetHttpRequest(url);
            request.Headers.Add("X-Requested-With", "XMLHttpRequest");
            request.Accept = "application/json, text/javascript, */*; q=0.01";
            request.Referer = "http://zhidao.baidu.com/";
            request.Headers.Add("Accept-Language", "en-US,en;q=0.8,zh-Hans-CN;q=0.5,zh-Hans;q=0.3");
            request.Headers.Add("Accept-Encoding", "gzip, deflate");
            request.Host = "zhidao.baidu.com";
            request.Headers.Add("DNT", "1");
            request.CookieContainer = new CookieContainer();
            request.CookieContainer.Add(collection);
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            return response;
        }

        /// <summary>
        /// 获取登录信息
        /// </summary>
        /// <param name="collection"></param>
        /// <returns></returns>
        public static HttpWebResponse GetLoginInfoResponse(CookieCollection collection)
        {
            string url = BaseUrl + "/api/loginInfo?t=" + DateTime.UtcNow.GetTime();
            HttpWebRequest request = HttpWebRequestUtility.CreateGetHttpRequest(url);
            request.Headers.Add("X-Requested-With", "XMLHttpRequest");
            request.Accept = "*/*";
            request.Referer = "http://zhidao.baidu.com/";
            request.Headers.Add("Accept-Language", "en-US,en;q=0.8,zh-Hans-CN;q=0.5,zh-Hans;q=0.3");
            request.Headers.Add("Accept-Encoding", "gzip, deflate");
            request.Host = "zhidao.baidu.com";
            request.Headers.Add("DNT", "1");
            request.CookieContainer = new CookieContainer();
            request.CookieContainer.Add(collection);
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            return response;
        }

        /// <summary>
        /// 获取登录信息
        /// </summary>
        /// <returns></returns>
        public static HttpWebResponse GetApiInfo(CookieCollection collection)
        {
            string url = PassportUrl + "/v2/api/?getapi&tpl=ik&apiver=v3&tt=" + DateTime.UtcNow.GetTime() + "&class=login&logintype=dialogLogin&callback=bd__cbs__" + AnyRadixConvert.H2X((long)(Math.Floor((new Random()).NextDouble() * 2147483648)), 36).ToLower();
            HttpWebRequest request = HttpWebRequestUtility.CreateGetHttpRequest(url);
            request.Accept = "application/javascript, */*;q=0.8";
            request.Referer = "http://zhidao.baidu.com/";
            request.Headers.Add("Accept-Language", "en-US,en;q=0.8,zh-Hans-CN;q=0.5,zh-Hans;q=0.3");
            request.Headers.Add("Accept-Encoding", "gzip, deflate");
            request.Host = "passport.baidu.com";
            request.Headers.Add("DNT", "1");
            request.CookieContainer = new CookieContainer();
            request.CookieContainer.Add(collection[0]);
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            return response;
        }

        /// <summary>
        /// 登陆前检查
        /// </summary>
        /// <param name="token"></param>
        /// <param name="username"></param>
        /// <param name="collection"></param>
        /// <returns></returns>
        public static HttpWebResponse LoginCheck(string token, string username, CookieCollection collection)
        {
            string url = PassportUrl + "/v2/api/?logincheck&token=" + token + "&tpl=ik&apiver=v3&tt=" + DateTime.UtcNow.GetTime() + "&username=" + System.Web.HttpUtility.UrlEncode(username) + "&isphone=false&callback=bd__cbs__" + AnyRadixConvert.H2X((long)(Math.Floor((new Random()).NextDouble() * 2147483648)), 36).ToLower();
            HttpWebRequest request = HttpWebRequestUtility.CreateGetHttpRequest(url);
            request.Accept = "application/javascript, */*;q=0.8";
            request.Headers.Add("Accept-Encoding", "gzip, deflate");
            request.Headers.Add("Accept-Language", "en-US,en;q=0.8,zh-Hans-CN;q=0.5,zh-Hans;q=0.3");
            request.Headers.Add("DNT", "1");
            request.Referer = "http://zhidao.baidu.com/";
            request.Host = "passport.baidu.com";
            request.CookieContainer = new CookieContainer();
            request.CookieContainer.Add(collection);
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            return response;
        }

        /// <summary>
        /// 登陆百度
        /// </summary>
        /// <returns></returns>
        public static HttpWebResponse Login(string data, CookieCollection collection)
        {
            Encoding encoding = Encoding.ASCII;
            byte[] bytes = encoding.GetBytes(data);
            string url = PassportUrl + "/v2/api/?login";
            HttpWebRequest request = HttpWebRequestUtility.CreatePostHttpRequest(url);
            request.Accept = "text/html, application/xhtml+xml, */*";
            request.Referer = "http://zhidao.baidu.com/";
            request.Headers.Add("Accept-Language", "en-US,en;q=0.8,zh-Hans-CN;q=0.5,zh-Hans;q=0.3");
            request.ContentType = "application/x-www-form-urlencoded";
            request.ContentLength = bytes.Length;
            request.Headers.Add("Accept-Encoding", "gzip, deflate");
            request.Host = "passport.baidu.com";
            request.Headers.Add("DNT", "1");
            request.Headers.Add("Cache-Control", "no-cache");
            request.CookieContainer = new CookieContainer();
            request.CookieContainer.Add(collection);
            request.ServicePoint.Expect100Continue = false;
            request.KeepAlive = true;
            Stream stream = request.GetRequestStream();
            stream.Write(bytes, 0, bytes.Length);
            stream.Close();            
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();            
            return response;
        }

        /// <summary>
        /// 刷新百度知道首页
        /// </summary>
        /// <param name="collection"></param>
        /// <returns></returns>
        public static HttpWebResponse Refresh(CookieCollection collection)
        {
            HttpWebRequest request = HttpWebRequestUtility.CreateGetHttpRequest(BaseUrl + "/");
            request.Accept = "text/html, application/xhtml+xml, */*";
            request.Headers.Add("Accept-Language", "en-US,en;q=0.8,zh-Hans-CN;q=0.5,zh-Hans;q=0.3");
            request.Headers.Add("Accept-Encoding", "gzip, deflate");
            request.Host = "zhidao.baidu.com";
            request.Headers.Add("DNT", "1");
            request.Headers.Add("Cache-Control", "no-cache");
            request.CookieContainer = new CookieContainer();
            request.CookieContainer.Add(collection);
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            return response;
        }

        /// <summary>
        /// 获取用户信息
        /// </summary>
        /// <param name="collection"></param>
        /// <returns></returns>
        public static HttpWebResponse GetUserInfo(CookieCollection collection)
        {
            string url = BaseUrl + "/api/loginInfo?t=" + DateTime.UtcNow.GetTime();
            HttpWebRequest request = HttpWebRequestUtility.CreateGetHttpRequest(url);
            request.Accept = "*/*";
            request.Headers.Add("Accept-Encoding", "gzip, deflate");
            request.Headers.Add("Accept-Language", "en-US,en;q=0.8,zh-Hans-CN;q=0.5,zh-Hans;q=0.3");
            request.Headers.Add("DNT", "1");
            request.Referer = "http://zhidao.baidu.com/";
            request.Headers.Add("X-Requested-With", "XMLHttpRequest");
            request.Host = "zhidao.baidu.com";
            request.CookieContainer = new CookieContainer();
            request.CookieContainer.Add(collection);
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            return response;
        }

        /// <summary>
        /// 获取全部关键字对应的问题
        /// </summary>
        /// <param name="collection"></param>
        /// <returns></returns>
        public static HttpWebResponse GetAllKeywordQuestions(CookieCollection collection)
        {
            string url = BaseUrl + "/home/api/carekeyword?rn=14&t=" + DateTime.Now.GetTime();
            HttpWebRequest request = HttpWebRequestUtility.CreateGetHttpRequest(url);
            request.Accept = "application/json, text/javascript, */*; q=0.01";
            request.Headers.Add("Accept-Encoding", "gzip, deflate");
            request.Headers.Add("Accept-Language", "en-US,en;q=0.8,zh-Hans-CN;q=0.5,zh-Hans;q=0.3");
            request.Headers.Add("DNT", "1");
            request.Referer = "http://zhidao.baidu.com/";
            request.Headers.Add("X-Requested-With", "XMLHttpRequest");
            request.Host = "zhidao.baidu.com";
            request.CookieContainer = new CookieContainer();
            request.CookieContainer.Add(collection);
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            return response;
        }

        /// <summary>
        /// 提交回答
        /// </summary>
        /// <param name="collection"></param>
        /// <param name="qid"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        public static HttpWebResponse SubmitAnswer(CookieCollection collection, string qid, string data)
        {
            string url = BaseUrl + "/submit/ajax/";
            HttpWebRequest request = HttpWebRequestUtility.CreatePostHttpRequest(url);
            request.Accept = "application/json, text/javascript, */*; q=0.01";
            request.ContentType = "application/x-www-form-urlencoded; charset=UTF-8";            
            request.Headers.Add("X-Requested-With", "XMLHttpRequest");
            request.Referer = "http://zhidao.baidu.com/question/" + qid + ".html?push=keyword";
            request.Headers.Add("Accept-Language", "en-US,en;q=0.8,zh-Hans-CN;q=0.5,zh-Hans;q=0.3");
            request.Headers.Add("Accept-Encoding", "gzip, deflate");
            request.Host = "zhidao.baidu.com";
            request.Headers.Add("DNT", "1");            
            request.Headers.Add("Cache-Control", "no-cache");
            request.CookieContainer = new CookieContainer();
            request.CookieContainer.Add(collection);
            Encoding encoding = Encoding.ASCII;
            byte[] bytes = encoding.GetBytes(data);
            request.ContentLength = bytes.Length;
            Stream stream = request.GetRequestStream();
            stream.Write(bytes, 0, bytes.Length);
            stream.Close();            
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            return response;
        }

        #region 生成Hm_lvt和Hm_lpvt Cookie
        public static Cookie HmLvtCookieHandler(string id, string hostname, string url)
        {
            decimal J = Math.Round(decimal.Parse(DateTime.UtcNow.GetTime().ToString()) / 1000);
            long age = 31536000000;
            Cookie cookie = new Cookie("Hm_lvt_" + id, J.ToString());
            cookie.Domain = ta(hostname);
            cookie.Path = ua(url);
            cookie.Secure = false;
            cookie.Expires = DateTime.UtcNow.AddTicks(age);
            return cookie;
        }

        public static Cookie HmLpvtCookieHandler(string id, string hostname, string url)
        {
            decimal J = Math.Round(decimal.Parse(DateTime.UtcNow.GetTime().ToString()) / 1000);
            Cookie cookie = new Cookie("Hm_lpvt_" + id, J.ToString());
            cookie.Domain = ta(hostname);
            cookie.Path = ua(url);
            cookie.Secure = false;
            cookie.Expires = DateTime.MinValue;
            return cookie;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="url">完整的URL</param>
        /// <returns></returns>
        private static string ua(string url)
        {
            string[] dm = { "zhidao.baidu.com" };
            for (int a = 0; a < dm.Length; a++)
            {
                string d = dm[a];
                if (d.IndexOf('/') > -1 && Ia(url, d))
                {
                    Regex re = new Regex("^[^/]+(/.*)");
                    return re.Replace(d, "$1") + "/";
                }
            }
            return "/";
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="hostname">域名</param>
        /// <returns></returns>
        private static string ta(string hostname)
        {
            string[] dm = { "zhidao.baidu.com" };
            for (int b = 0, d = dm.Length; b < d; b++)
            {
                if (V(hostname, dm[b]))
                {
                    Regex re = new Regex("(:\\d+)?[\\/\\?#].*");
                    return re.Replace(dm[b], "");
                }
            }
            return hostname;
        }

        private static bool V(string a, string b)
        {
            Regex re = new Regex(":\\d+");
            a = "." + re.Replace(a, "");
            b = "." + re.Replace(b, "");
            int d = a.IndexOf(b);
            return -1 < d && d + b.Length == a.Length;
        }

        private static bool Ia(string a, string b)
        {
            Regex re = new Regex("^https?:\\/\\/");
            a = re.Replace(a, "");
            return a.IndexOf(b) == 0;
        }
        #endregion
    }
}
